<template>
  <div id="app">
    <div>
      <div v-for="item in screens" :key="item.id">
        <button @click="changeScreen(item)">changeScreen</button>
      </div>
    </div>
    <div>
      appId:<input type="text" v-model="appId" /> token:<input
        type="text"
        v-model="token"
      /><br />
      channel:<input type="text" v-model="channel" /> userId:<input
        type="text"
        v-model="userId"
      />
      <br />
      <br />
      <button @click="init">init</button>
      <button @click="start" v-show="!connectStatus">start</button>
      <button @click="pushVideo()">pushVideo</button>
      <button @click="stop" v-show="connectStatus">stop</button>
      <br />
      <br />
      RtmToken:<input type="text" v-model="rtmToken" />
      <br />
      msg:<input type="text" v-model="peerMessage" />
      <button @click="sendMsg">sendMsg</button>
    </div>
    <div class="hello"> 
      <h4>Local video</h4>
      <div class="video" id="me"></div>
      <h4>Remote video</h4>
      <div class="video" id="remote-container"></div>
    </div>
    <div id="console"></div>
    <div id="log"></div>
  </div>
</template>

<script>
import Hello from "./components/Hello.vue";
import AgoraRtcEngine from "agora-electron-sdk";
import AgoraRTC from "agora-rtc-sdk";
import AgoraRTM, { RtmClient } from "agora-rtm-sdk";
import path from "path";
import os from "os";
import { rejects } from "assert";

// With shell.openExternal(url) is how
// external urls must be handled, not href
const shell = require("electron").shell;

// 处理错误的函数
const handleError = function(err) {
  console.log("Error: ", err);
  alert("【err.info】:" + err.info + ",【err.msg】:" + err.msg);
}; 

export default {
  components: {
    Hello,
  },
  data() {
    return {
      appId: "06943e33caee4e80a23a6cb42f223c02",
      token:
        "00606943e33caee4e80a23a6cb42f223c02IAD/U+7Q0IY719rhugqbV8fbdrV8hyQ3N8WG4IuFvAhTf6DfQtYAAAAAEAD4YHXYvOucYAEAAQC665xg",
      channel: "demo",
      userId: "qinzhou",
      rtcClient: AgoraRTC.createClient({
        mode: "rtc",
        codec: "vp8",
      }),
      rtmCliemt: null,
      connectStatus: 0,
      localStreams: [],

      screens: [],
      peerId: null,
      rtmToken:
        "00606943e33caee4e80a23a6cb42f223c02IADSjC3axGyPwgCyOl0PXQjTNpvThBs6c47u0aThBFa6teS7xl4AAAAAEABGR0zoJ8mcYAEA6AMnyZxg",
      peerMessage: "",
    };
  },
  methods: {
    link: (url) => {
      shell.openExternal(url);
    },
    stop() {},
    async changeScreen(item) {
      document.querySelector("#me").removeChild(document.querySelector("#me").children[0])
      this.rtcClient.unpublish(this.localStream);
      await this.pushVideo(item.id);
    },
    start() {
      let rtmCliemt = AgoraRTM.createInstance(this.appId, {
        enableLogUpload: false,
      });

      // 加入频道
      this.rtcClient.join(
        this.token,
        this.channel,
        this.userId,
        async (uid) => {
          // 保存本地屏幕共享流的 uid
          this.localStreams.push(uid);

          // this.userId = uid;
          //实时消息登录
          await rtmCliemt.login({
            uid: this.userId,
            token: this.rtmToken,
          });

          console.log("uid=", uid);

          this.registAdd();
          this.registRemove();

          this.rtmCliemt = rtmCliemt;
          this.registMsgEvent();
        },
        handleError
      );
    },
    //获取屏幕
    getScreenSources() {
      return new Promise((reslove, reject) => {
        AgoraRTC.getScreenSources((err, sources) => {
          if (err) {
            rejects(err);
          } else {
            const screens = [];
            for (const item of sources) {
              if (item.id.includes("screen")) {
                screens.push(item);
              }
            }
            reslove(screens);
          }
        });
      });
    },
    async pushVideo(sourceId) {
      const streamSpec = {
        // audio: true,
        // video: true,
        audio: false,
        video: false,
        screen: true,
        screenAudio: false,
        mediaSource: "screen", //"screen" | "application" | "window"
        sourceId: sourceId,
        optimizationMode:"motion", //"motion": 流畅优先 | "detail": 清晰优先
      };
      if (!streamSpec.sourceId) {
        try {
          this.screens = await this.getScreenSources();
          if (this.screens.length > 0) {
            streamSpec.sourceId = this.screens[0].id;
          }
        } catch (error) {
          alert("没有可以默认的数据");
        }
      }

      // 根据浏览器类型设置相关属性
      // 注意你需要自己实现判断浏览器的功能
      // if (isFirefox()) {
      //   streamSpec.mediaSource = "window";
      // } else if (!isCompatibleChrome()) {
      //   streamSpec.extensionId = "minllpmhdgpndnkomcoccfekfegnlikg";
      // }

      let localStream = AgoraRTC.createStream(streamSpec);
      // 使用 setVideoEncoderConfiguration 设置视频属性
      localStream.setVideoEncoderConfiguration({
        // 视频分辨率
        resolution: {
          width: 640,
          height: 480,
        },
        // 视频编码帧率。通常建议是 15 帧，不超过 30 帧
        frameRate: {
          min: 22,
          max: 30,
        },
        // 码率。我们建议参考下面的视频属性参考表进行设置
        bitrate: {
          min: 1000,
          max: 5000,
        },
      });

      // 使用 setVideoProfile 设置视频属性
      // 设置视频属性为 480p_3，对应分辨率 480 x 480，帧率 15， 码率 400
      localStream.setVideoProfile("480p_4");

      // 初始化本地流
      localStream.init(() => {
        // 播放本地流
        localStream.play("me");
        // 发布本地流
       
        this.rtcClient.publish(localStream);
        this.localStream=localStream
      }, handleError);
    },
    registAdd() {
      // 有远端用户发布流时进行订阅
      this.rtcClient.on("stream-added", (evt) => {
        // 收到流加入频道的事件后，先判定是不是本地的 uid
        if (!this.localStreams.includes(evt.stream.getId())) {
          // 订阅流
          this.rtcClient.subscribe(evt.stream, handleError);
        }
      });
      // 订阅成功后播放远端用户的流
      this.rtcClient.on("stream-subscribed", (evt) => {
        let stream = evt.stream;
        let streamId = String(stream.getId());
        this.addVideoStream(streamId);
        stream.play(streamId);
      });
    },
    registRemove() {
      // 远端用户取消发布流时，关闭及移除对应的流。
      this.rtcClient.on("stream-removed", (evt) => {
        let stream = evt.stream;
        let streamId = String(stream.getId());
        stream.close();
        this.removeVideoStream(streamId);
      });
      // 远端用户离开频道时，关闭及移除对应的流。
      this.rtcClient.on("peer-leave", (evt) => {
        let stream = evt.stream;
        let streamId = String(stream.getId());
        stream.close();
        this.removeVideoStream(streamId);
      });
    },
    async registMsgEvent() {
      // 客户端事件监听
      // 显示对端发送的消息
      this.rtmCliemt.on("MessageFromPeer", (message, peerId) => {
        //互相打招呼
        if (
          message.messageType == "TEXT" &&
          message.text == "hi" &&
          peerId != this.userId
        ) {
          this.peerId = peerId;
        }

        document
          .getElementById("log")
          .appendChild(document.createElement("div"))
          .append(
            "Message from: " + peerId + " Message: " + JSON.stringify(message)
          );
      });
      // 显示连接状态变化
      this.rtmCliemt.on("ConnectionStateChanged", function(state, reason) {
        document
          .getElementById("log")
          .appendChild(document.createElement("div"))
          .append("State changed To: " + state + " Reason: " + reason);
      });

      let channel = this.rtmCliemt.createChannel("demoChannel");

      channel.on("ChannelMessage", function(message, memberId) {
        document
          .getElementById("log")
          .appendChild(document.createElement("div"))
          .append(
            "Message received from: " + memberId + " Message: " + message
          );
      });
      // 显示频道
      channel.on("MemberJoined", (memberId) => {
        //这里只取非自己的第一个
        if (memberId != this.userId) {
          this.peerId = memberId;
          this.peerMessage = "hi";
          //向对方打招呼
          this.sendMsg();
          this.peerMessage = "";
        }
        document
          .getElementById("log")
          .appendChild(document.createElement("div"))
          .append(memberId + " joined the channel");
      });
      // 频道成员
      channel.on("MemberLeft", function(memberId) {
        document
          .getElementById("log")
          .appendChild(document.createElement("div"))
          .append(memberId + " left the channel");
      });

      //加入频道
      await channel.join().then(() => {
        document
          .getElementById("log")
          .appendChild(document.createElement("div"))
          .append("You have successfully joined channel " + channel.channelId);
      });
    },
    async sendMsg() {
      console.log("this.peerId=", this.peerId);
      await this.rtmCliemt
        .sendMessageToPeer({ text: this.peerMessage }, this.peerId)
        .then((sendResult) => {
          if (sendResult.hasPeerReceived) {
            document
              .getElementById("log")
              .appendChild(document.createElement("div"))
              .append(
                "Message has been received by: " +
                  this.peerId +
                  " Message: " +
                  this.peerMessage
              );
          } else {
            document
              .getElementById("log")
              .appendChild(document.createElement("div"))
              .append(
                "Message sent to: " +
                  this.peerId +
                  " Message: " +
                  this.peerMessage
              );
          }
        });
    },
    init() {
      if (!this.appId) {
        alert("appId不能为空！");
        return;
      }
      this.rtcClient.init(
        this.appId,
        () => {
          console.log("rtcClient initialized");
        },
        (err) => {
          console.log("rtcClient init failed ", err);
        }
      );
    },
    // 将视频流添加到远端视频画面容器的函数
    addVideoStream(elementId) {
      // 定义远端视频画面的容器
      let remoteContainer = document.getElementById("remote-container");
      // 给每个流创建一个 div
      let streamDiv = document.createElement("div");
      // 将 elementId 分配到 div
      streamDiv.id = elementId;
      // 处理镜像问题
      // streamDiv.style.transform = "rotateY(180deg)";
      // 将 div 添加到容器
      remoteContainer.appendChild(streamDiv);
    },
    removeVideoStream(elementId) {
      let remoteDiv = document.getElementById(elementId);
      if (remoteDiv) remoteDiv.parentNode.removeChild(remoteDiv);
    },
  },

  mounted: function() {},
};
</script>

<style>
* {
  font-family: sans-serif;
}
h1,
h4 {
  text-align: center;
}
#me {
  position: relative;
  width: 50%;
  margin: 0 auto;
  display: block;
}
#me video {
  position: relative !important;
}
#remote-container {
  display: flex;
}
#remote-container video {
  height: auto;
  position: relative !important;
}
</style>
